const WebSocket = require('ws');
const { v4: uuidv4 } = require('uuid');
const UserManager = require('./user-manager');

class SignalingServer {
  constructor(server) {
    this.wss = new WebSocket.Server({ server });
    this.userManager = new UserManager();
    
    this.setupWebSocket();
  }

  setupWebSocket() {
    this.wss.on('connection', (ws) => {
      console.log('新的WebSocket连接');
      
      ws.on('message', (data) => {
        try {
          const message = JSON.parse(data);
          this.handleMessage(ws, message);
        } catch (error) {
          console.error('消息解析错误:', error);
          this.sendError(ws, '消息格式错误');
        }
      });

      ws.on('close', () => {
        console.log('WebSocket连接关闭');
        const user = this.userManager.removeUser(ws);
        if (user) {
          this.broadcastUserList();
        }
      });

      ws.on('error', (error) => {
        console.error('WebSocket错误:', error);
      });
    });
  }

  /**
   * 处理WebSocket接收到的消息
   * 
   * @param {WebSocket} ws - 客户端WebSocket连接对象
   * @param {Object} message - 接收到的消息对象
   * @param {string} message.type - 消息类型
   * @param {Object} message.data - 消息数据
   * 
   * @description
   * 根据不同的消息类型调用对应的处理函数：
   * - login: 处理登录请求
   * - call_request: 处理呼叫请求
   * - call_response: 处理呼叫响应
   * - offer: 处理WebRTC offer
   * - answer: 处理WebRTC answer
   * - ice_candidate: 处理ICE候选
   * - hangup: 处理挂断请求
   * - 其他: 返回未知类型错误
   */
  handleMessage(ws, message) {
    const { type, data } = message;

    switch (type) {
      case 'login':
        this.handleLogin(ws, data);
        break;
      case 'call_request':
        this.handleCallRequest(ws, data);
        break;
      case 'call_response':
        this.handleCallResponse(ws, data);
        break;
      case 'offer':
        this.handleOffer(ws, data);
        break;
      case 'answer':
        this.handleAnswer(ws, data);
        break;
      case 'ice_candidate':
        this.handleIceCandidate(ws, data);
        break;
      case 'hangup':
        this.handleHangup(ws, data);
        break;
      default:
        console.log('未知消息类型:', type);
        this.sendError(ws, '未知消息类型');
    }
  }

  // 处理用户登录
  handleLogin(ws, data) {
    const { userName } = data;
    
    // 验证用户名不为空
    if (!userName) {
      this.sendError(ws, '用户名不能为空');
      return;
    }

    // 生成唯一用户ID并添加用户
    const userId = uuidv4();
    const user = this.userManager.addUser(userId, userName, ws);

    // 发送登录成功响应
    this.sendTo(ws, {
      type: 'login_success',
      data: {
        userId,
        userName,
        onlineUsers: this.userManager.getOnlineUsers()
      }
    });

    // 广播更新用户列表
    this.broadcastUserList();
  }

  /**
   * 处理呼叫请求
   * 
   * @param {WebSocket} ws - 发起呼叫的用户WebSocket连接
   * @param {Object} data - 呼叫请求数据
   * @param {string} data.toUserId - 被呼叫用户的ID
   * 
   * @description
   * 验证呼叫请求的有效性，包括：
   * - 检查主叫用户是否已登录
   * - 检查被叫用户是否在线
   * - 检查被叫用户是否正在通话中
   * 
   * 验证通过后：
   * - 设置双方用户的通话状态为通话中
   * - 向被叫用户发送呼叫请求通知
   * - 广播更新用户列表
   */
  handleCallRequest(ws, data) {
    const fromUser = this.userManager.getUserBySocket(ws);
    const { toUserId } = data;

    if (!fromUser) {
      this.sendError(ws, '请先登录');
      return;
    }

    const toUser = this.userManager.getUser(toUserId);
    if (!toUser || !toUser.online) {
      this.sendError(ws, '用户不在线');
      return;
    }

    if (toUser.inCall) {
      this.sendError(ws, '用户正在通话中');
      return;
    }

    // 设置用户通话状态
    this.userManager.setUserInCall(fromUser.id, true);
    this.userManager.setUserInCall(toUserId, true);

    // 发送呼叫请求给被叫方
    this.sendTo(toUser.ws, {
      type: 'call_request',
      data: {
        fromUserId: fromUser.id,
        fromUserName: fromUser.name
      }
    });

    // 广播更新用户列表
    this.broadcastUserList();
  }

  // 处理呼叫响应
  handleCallResponse(ws, data) {
    const user = this.userManager.getUserBySocket(ws);
    const { toUserId, accepted } = data;

    if (!user) {
      this.sendError(ws, '请先登录');
      return;
    }

    const toUser = this.userManager.getUser(toUserId);
    if (!toUser || !toUser.online) {
      this.sendError(ws, '用户不在线');
      return;
    }

    // 发送呼叫响应给主叫方
    this.sendTo(toUser.ws, {
      type: 'call_response',
      data: {
        fromUserId: user.id,
        fromUserName: user.name,
        accepted
      }
    });

    if (!accepted) {
      // 如果拒绝通话，重置通话状态
      this.userManager.setUserInCall(user.id, false);
      this.userManager.setUserInCall(toUserId, false);
      this.broadcastUserList();
    }
  }

  // 处理 WebRTC Offer
  handleOffer(ws, data) {
    const fromUser = this.userManager.getUserBySocket(ws);
    const { toUserId, offer } = data;

    if (!fromUser) {
      this.sendError(ws, '请先登录');
      return;
    }

    const toUser = this.userManager.getUser(toUserId);
    if (!toUser || !toUser.online) {
      this.sendError(ws, '用户不在线');
      return;
    }

    // 转发 Offer 给被叫方
    this.sendTo(toUser.ws, {
      type: 'offer',
      data: {
        fromUserId: fromUser.id,
        offer
      }
    });
  }

  // 处理 WebRTC Answer
  handleAnswer(ws, data) {
    const fromUser = this.userManager.getUserBySocket(ws);
    const { toUserId, answer } = data;

    if (!fromUser) {
      this.sendError(ws, '请先登录');
      return;
    }

    const toUser = this.userManager.getUser(toUserId);
    if (!toUser || !toUser.online) {
      this.sendError(ws, '用户不在线');
      return;
    }

    // 转发 Answer 给主叫方
    this.sendTo(toUser.ws, {
      type: 'answer',
      data: {
        fromUserId: fromUser.id,
        answer
      }
    });
  }

  // 处理 ICE 候选
  handleIceCandidate(ws, data) {
    const fromUser = this.userManager.getUserBySocket(ws);
    const { toUserId, candidate } = data;

    if (!fromUser) {
      this.sendError(ws, '请先登录');
      return;
    }

    const toUser = this.userManager.getUser(toUserId);
    if (!toUser || !toUser.online) {
      this.sendError(ws, '用户不在线');
      return;
    }

    // 转发 ICE 候选
    this.sendTo(toUser.ws, {
      type: 'ice_candidate',
      data: {
        fromUserId: fromUser.id,
        candidate
      }
    });
  }

  // 处理挂断
  handleHangup(ws, data) {
    const user = this.userManager.getUserBySocket(ws);
    const { toUserId } = data;

    if (!user) {
      this.sendError(ws, '请先登录');
      return;
    }

    // 重置通话状态
    this.userManager.setUserInCall(user.id, false);

    // 如果指定了对方，也重置对方状态并通知
    if (toUserId) {
      this.userManager.setUserInCall(toUserId, false);
      const toUser = this.userManager.getUser(toUserId);
      if (toUser && toUser.online) {
        this.sendTo(toUser.ws, {
          type: 'hangup',
          data: {
            fromUserId: user.id
          }
        });
      }
    }

    // 广播更新用户列表
    this.broadcastUserList();
  }

  // 发送消息给指定 WebSocket
  sendTo(ws, message) {
    if (ws.readyState === WebSocket.OPEN) {
      ws.send(JSON.stringify(message));
    }
  }

  // 发送错误消息
  sendError(ws, errorMessage) {
    this.sendTo(ws, {
      type: 'error',
      data: { message: errorMessage }
    });
  }

  // 广播用户列表给所有客户端
  broadcastUserList() {
    const userList = this.userManager.getOnlineUsers();
    const message = {
      type: 'user_list',
      data: { users: userList }
    };

    this.wss.clients.forEach(client => {
      if (client.readyState === WebSocket.OPEN) {
        client.send(JSON.stringify(message));
      }
    });
  }
}

module.exports = SignalingServer;